from __future__ import print_function
from time import clock
import numpy as np
from numpy.linalg import norm
from operator import attrgetter

log = print


def load_map():
    from osm_utils import CountryMap
    road_map = CountryMap()
    road_map.LoadMap()
    return road_map


class Acc(object):
    min = float('inf')
    max = -min
    sum = count = 0

    def __init__(self, attr):
        self.get = attrgetter(attr)

    def add(self, elem):
        e = self.get(elem)
        self.max = max(e, self.max)
        self.min = min(e, self.min)
        self.sum += e
        self.count += 1


def timed(f):
    def wrap(*x, **d):
        start = clock()
        res = f(*x, **d)
        res.time = clock() - start
        return res
    return wrap


def read_csv_file(filename='ProblemSet100.csv'):
    with open(filename) as f:
        return [tuple(int(i) for i in line.strip().split(','))
                for line in f]

from threading import Lock


class save_to():
    lck = Lock()

    def __init__(self, filename):
        self.filename = filename

    def __call__(self, run):
        lst = [',{', '.total_nodes},{', '.time},{', '.path_cost:.2f}']
        x = [str(i).join(lst)
                 for i in range(2, 5)]
        fmt = '{0},{1}' + ''.join(x) + '\n'

        def wrap(*x, **d):
            for s, g, line in run(*x, **d):
                with save_to.lck, open(self.filename, 'a') as f:
                    f.write(fmt.format(s, g, *line))
        return wrap


class FileProperty:
    def __init__(self, filename):
        self.filename = filename
        self.v = None

    @property
    def values(self):
        if self.v is None:
            with open(self.filename) as f:
                self.v = tuple(float(x) for x in f.read().strip().split(','))
        return self.v

    @values.setter
    def values(self, gammas):
        self.v = gammas
        with open(self.filename, 'w') as f:
            f.write('{},{},{}'.format(*gammas))

gamma = FileProperty('conversion.csv')


def is_turn(vec_a, vec_b):
    ua, ub = vec_a / (norm(vec_a) or 1), vec_b / (norm(vec_b) or 1)
    if (ua == ub).all():
        return 0
    return np.dot(ua, ub) > -0.3420201433256687


def get_latlon(junction):
    return np.array([junction.lat, junction.lon])


def test_angle(xa, xb):
    a, b = np.array(xa), np.array(xb)
    print(is_turn(a, b))

if __name__ == '__main__':
    test_angle([0, 1], [1, 0])
    test_angle([1, 0], [-10, 1])
    test_angle([1, 0], [1, 1])
    test_angle([1, 0], [-1, 1])
    test_angle([1, 0], [-1, 2.8])
